package com.example.web.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;

import com.example.web.api.CodeItem;
import com.example.web.bo.DemoBO;
import com.example.web.bo.Person;
import com.example.web.dao.TransactionDAO;
import com.outstanding.framework.base.OutstandingService;
import com.outstanding.framework.base.OutstandingTransactionTemplate;
import com.outstanding.framework.core.Context;
import com.outstanding.framework.core.PendingException;
import com.outstanding.framework.core.SysCode;

/**
 * 带事务的服务： 1. 所有有事务要求的逻辑都必须有Service具体的实现，即事务的控制都由service来完成。 2.
 * 2.事务理论上建议大家通过显示代码来进行控制，而不通过注解控制。
 * 
 * @author Devin
 *
 */

@Service
public class TransactionService extends OutstandingService {

	/**
	 * 新事务的模版
	 */
	@Autowired
	private OutstandingTransactionTemplate newTransactionTemplate;

	public OutstandingTransactionTemplate getNewTransactionTemplate() {
		return newTransactionTemplate;
	}

	public void setNewTransactionTemplate(OutstandingTransactionTemplate newTransactionTemplate) {
		this.newTransactionTemplate = newTransactionTemplate;
	}

	@Autowired
	private TransactionDAO dao;

	@Autowired
	private CalledService service;

	/**
	 * 以下两个方法是演示 单服务事务情况。
	 * 
	 * @param bo
	 * @throws PendingException
	 */

	public void commit(final DemoBO bo) throws PendingException {

		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				int count = 0; // 受影响的行数

				debug("调用commitSuccess");
				count = dao.insert(bo);
				debug(String.valueOf(bo.getId()));
				if (count == 1) {
					return SysCode.SUCCESS;
				} else {
					status.setRollbackOnly();
					throw new PendingException(CodeItem.T0001, "SQL执行异常");
				}

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}

	}

	public void submitrolleback(final DemoBO bo) throws PendingException {

		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				int count = 0; // 受影响的行数

				debug("调用submitrolleback");
				List<DemoBO> list = dao.select();
				count = dao.insert(bo);
				// 此处完全是为了演示，实际编码时，应该先检查，再调用DAO层访问数据库才是合理的。
				if ("sss".equals(bo.getName())) {
					throw new PendingException(CodeItem.T0005, "业务规则不通过");
				}
				if (count == 1) {
					return SysCode.SUCCESS;
				} else {
					status.setRollbackOnly();
					throw new PendingException(CodeItem.T0001, "SQL执行异常");
				}

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/* 单服务情况演示结束 */

	/**
	 * 开始演示事务的传播属性：同生同死，两个都提交
	 * 
	 * @param bo
	 * @throws PendingException
	 */
	public void callService(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				int count = 0; // 受影响的行数
				debug("调用callService1");
				count = dao.insert(bo);
				Person p = new Person();
				service.submitForce(p);
				if (count == 1) {
					return SysCode.SUCCESS;
				} else {
					status.setRollbackOnly();
					throw new PendingException(CodeItem.T0001, "SQL执行异常");
				}

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/**
	 * 开始演示事务的传播属性：同生同死，因外部service异常，最后都回滚。
	 * 
	 * @param bo
	 * @throws PendingException
	 */
	public void callService1(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				int count = 0; // 受影响的行数

				debug("调用callService1");
				count = dao.insert(bo);
				Person p = new Person();
				service.submitForce(p);
				if (count == 1) {
					status.setRollbackOnly();
					throw new PendingException(CodeItem.T0005, "业务不通过");
				}
				return SysCode.SUCCESS;

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/**
	 * 事务的传播属性：同生同死演示完毕 
	 * 开始事务的传播属性：各自为政，被调用方发生异常，调用方不回滚
	 */

	public void callService2(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				try {
					int count = 0; // 受影响的行数

					debug("调用callService1");
					count = dao.insert(bo);
					Person p = new Person();
					service.rollbackNew(p);
					if (count == 1) {
						return SysCode.SUCCESS;
					} else {
						status.setRollbackOnly();
						throw new PendingException(CodeItem.T0001, "SQL执行异常");
					}
				} catch (PendingException e) {
					if (e.getCode() == CodeItem.T0005) {
						// 继续逻辑

						return SysCode.SUCCESS;
					} else {
						throw e;
					}
				}

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/**
	 * 
	 * 事务的传播属性：各自为政，被调用方发生异常，调用方不处理，一起回滚
	 */
	public void callService3(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {

				int count = 0; // 受影响的行数

				debug("调用callService1");
				count = dao.insert(bo);
				Person p = new Person();
				service.rollbackNew(p);
				if (count == 1) {
					return SysCode.SUCCESS;
				} else {
					status.setRollbackOnly();
					throw new PendingException(CodeItem.T0001, "SQL执行异常");
				}

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/**
	 * 
	 * 事务的传播属性：各自为政，被调用方发生正常，调用方发生异常，调用方回滚，被调用方提交
	 */
	public void callService4(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {

				int count = 0; // 受影响的行数

				debug("调用callService1");
				count = dao.insert(bo);
				Person p = new Person();
				service.submitNew(p);
				if (count == 1) {
					status.setRollbackOnly();
					throw new PendingException(CodeItem.T0001, "SQL执行异常");
				}
				return SysCode.SUCCESS;

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/**
	 * 开始事务的传播属性：各自为政 演示结束
	 * 事务的传播属性：领导为大，因内部service异常，调用方捕获，并决定回滚，最后大家都回滚。
	 * 
	 * @param bo
	 * @throws PendingException
	 */
	public void callService5(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				int count = 0; // 受影响的行数
				try {
					debug("调用callService1");
					count = dao.insert(bo);
					Person p = new Person();
					service.rollbackNested(p);
					if (count == 1) {
						return SysCode.SUCCESS;
					} else {
						status.setRollbackOnly();
						throw new PendingException(CodeItem.T0001, "SQL执行异常");
					}
				} catch (PendingException e) {

					status.setRollbackOnly();
					throw e;
				}

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/**
	 * 事务的传播属性，领导为大，被调用方提交了，但由于调用方决定回滚了，所以大家都回滚了。
	 * 
	 * @param bo
	 * @throws PendingException
	 */

	public void callService6(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				int count = 0; // 受影响的行数

				debug("调用callService1");
				count = dao.insert(bo);
				Person p = new Person();
				service.submitNested(p);
				if (count == 1) {
					status.setRollbackOnly();
					throw new PendingException(CodeItem.T0005, "业务不通过");
				}
				return SysCode.SUCCESS;

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	/**
	 * 事务的传播属性，领导为大，被调用方回滚了，调用方自己选择不回滚了，所以被调用方回滚了，但调用方提交了。
	 * 
	 * @param bo
	 * @throws PendingException
	 */
	public void callService7(final DemoBO bo) throws PendingException {
		String result = newTransactionTemplate.execute(new TransactionCallback<String>() {

			/**
			 * 此方法必须抛出PendingException异常
			 */
			@Override
			public String doInTransaction(TransactionStatus status) throws PendingException {
				int count = 0; // 受影响的行数
				try{
					debug("调用callService1");
					count = dao.insert(bo);
					Person p = new Person();
					service.rollbackNested(p);
					if (count == 1) {
						return SysCode.SUCCESS;
					} else {
						status.setRollbackOnly();
						throw new PendingException(CodeItem.T0001, "SQL执行异常");
					}
				}catch(PendingException e){
					if(CodeItem.T0005.equals(e.getCode())){
						return SysCode.SUCCESS;
					}else{
						status.setRollbackOnly();
						throw e;
					}
				}

			}
		});

		if (!SysCode.isSuccess(result)) {
			throw new PendingException(result, "SQL执行异常");
		}
	}

	
}
